package com.satan.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.satan.constant.Constant;
import com.satan.dto.PageDto;
import com.satan.dto.UserPwdDto;
import com.satan.entity.SysMenu;
import com.satan.entity.SysRole;
import com.satan.entity.SysUser;
import com.satan.entity.SysUserRole;
import com.satan.entity.response.ResCode;
import com.satan.mapper.SysMenuMapper;
import com.satan.mapper.SysRoleMapper;
import com.satan.mapper.SysUserMapper;
import com.satan.mapper.SysUserRoleMapper;
import com.satan.service.SysUserRoleService;
import com.satan.service.SysUserService;
import com.satan.util.DateUtil;
import com.satan.util.StringUtil;
import com.satan.vo.SysUserVo;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Demon
 * @description 针对表【sys_user】的数据库操作Service实现
 * @createDate 2023-10-03 20:53:34
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
        implements SysUserService {
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Value("${avatarImagesFilePath}")
    private String avatarImagesFilePath;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Override
    public SysUser getUserByName(String username) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(SysUser::getUsername, username);
        SysUser sysUser = getOne(queryWrapper);
        return sysUser;
    }

    @Override
    public String getUserAuthority(Long userId) {
        StringBuffer authority = new StringBuffer();
        // 根据用户id获取所有的角色信息
        List<SysRole> roleList = sysRoleMapper.selectList(new QueryWrapper<SysRole>().inSql("id", "SELECT role_id FROM sys_user_role WHERE user_id=" + userId));
        if (roleList.size() > 0) {
            String roleCodeStrs = roleList.stream().map(r -> "ROLE_" + r.getCode()).collect(Collectors.joining(","));
            authority.append(roleCodeStrs);
        }
        // 遍历所有的角色，获取所有菜单权限 而且不重复
        Set<String> menuCodeSet = new HashSet<>();
        for (SysRole sysRole : roleList) {
            List<SysMenu> sysMenuList = sysMenuMapper.selectList(new QueryWrapper<SysMenu>().inSql("id", "SELECT menu_id FROM sys_role_menu WHERE role_id=" + sysRole.getId()));
            for (SysMenu sysMenu : sysMenuList) {
                String perms = sysMenu.getPerms();
                if (StrUtil.isNotEmpty(perms)) {
                    menuCodeSet.add(perms);
                }
            }
        }
        if (menuCodeSet.size() > 0) {
            authority.append(",");
            String menuCodeStrs = menuCodeSet.stream().collect(Collectors.joining(","));
            authority.append(menuCodeStrs);
        }
//        System.out.println("authority:"+authority.toString());
        return authority.toString();
    }

    @Override
    public Map<String, Object> uploadAvatar(MultipartFile file) throws IOException {
        Map<String, Object> resultMap = new HashMap<>();
        if (!file.isEmpty()) {
// 获取文件名
            String originalFilename = file.getOriginalFilename();
            String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFileName = DateUtil.getCurrentDateStr() + suffixName;
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File(avatarImagesFilePath + newFileName));
            resultMap.put("title", newFileName);
            resultMap.put("src", "image/userAvatar/" + newFileName);
        }
        return resultMap;
    }


    @Override
    public Map<String, Object> getPageList(PageDto pageDto) {
        String query=pageDto.getQuery().trim();
        Page<SysUser> pageResult = page(new Page<>
                (pageDto.getPageNum(), pageDto.getPageSize()),new LambdaQueryWrapper<SysUser>().like(StringUtil.isNotEmpty(query),SysUser::getUsername,query));
        List<SysUser> userList = pageResult.getRecords();
        List<SysUserVo> sysUserVoList = new ArrayList<>();
        for (SysUser sysUser : userList) {
            SysUserVo sysUserVo = new SysUserVo();
            BeanUtils.copyProperties(sysUser,sysUserVo);
            List<SysRole> sysRoleList = sysRoleMapper.selectList(new QueryWrapper<SysRole>().inSql("id", "SELECT role_id FROM sys_user_role WHERE user_id=" + sysUserVo.getId()));
            sysUserVo.setSysRoleList(sysRoleList);
            sysUserVoList.add(sysUserVo);
        }


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("userList", sysUserVoList);
        resultMap.put("total", pageResult.getTotal());
        return resultMap;
    }

    @Override
    public ResCode updateUserPwd(UserPwdDto userPwdDto, BCryptPasswordEncoder bCryptPasswordEncoder) {
        SysUser currentUser = getById(userPwdDto.getId());
        System.out.println("currentUser = " + currentUser);
        if (bCryptPasswordEncoder.matches(userPwdDto.getOldPassword(), currentUser.getPassword())) {
            currentUser.setPassword(bCryptPasswordEncoder.encode(userPwdDto.getNewPassword()));
            updateById(currentUser);
            return null;
        } else {
            return ResCode.OLD_PWD_ERROR;
        }
    }

    @Override
    public boolean updateAvatar(SysUser sysUser) {
        SysUser currentUser = getById(sysUser.getId());
        currentUser.setAvatar(sysUser.getAvatar());
        return updateById(currentUser);
    }

    @Override
    public boolean saveOrUpdateUser(SysUser sysUser,BCryptPasswordEncoder bCryptPasswordEncoder) {
        boolean b;
        if(sysUser.getId()==null){
            sysUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getPassword()));
            sysUser.setAvatar("default.jpg");
            b=save(sysUser);
        }else{
            b=updateById(sysUser);
        }
        return b;
    }


    @Override
    @Transactional
    public boolean deleteUserByIds(Long[] ids) {
        boolean b1 = removeByIds(Arrays.asList(ids));
        boolean b2 = sysUserRoleService.remove(new QueryWrapper<SysUserRole>().in("user_id", ids));
        return b1 && b2;
    }

    @Override
    public boolean resetPassword(Integer id,BCryptPasswordEncoder bCryptPasswordEncoder) {
        SysUser sysUser = getById(id);
        sysUser.setPassword(bCryptPasswordEncoder.encode(Constant.DEFAULT_PASSWORD));
        return  updateById(sysUser);
    }

    @Override
    public boolean updateStatus(Integer id, String status) {
        SysUser sysUser = getById(id);
        sysUser.setStatus(status);
        return saveOrUpdate(sysUser);
    }

}




